import { _decorator, Component, Prefab, Node, CCInteger, director, instantiate, Vec3 } from 'cc';
const { ccclass, property } = _decorator;

import UI from "../../Script/Manager/UI";
// import { CircleTheCat_GameData } from "./CircleTheCat_GameData";
import { CircleTheCat_GameStorage } from "./CircleTheCat_GameStorage";
import CircleTheCat_GamePanel from "./Script/UI/CircleTheCat_GamePanel";
import CircleTheCat_LosePanel from "./Script/UI/CircleTheCat_LosePanel";
import CircleTheCat_WinPanel from "./Script/UI/CircleTheCat_WinPanel";
import CircleTheCat_Grid from './CircleTheCat_Grid';

@ccclass('CircleTheCatGameManager')
export default class CircleTheCat_GameManager extends Component {
    static Instance: CircleTheCat_GameManager;
    @property({ type: Prefab, tooltip: "格子预设" })
    gridPrefab: Prefab | null = null;
    @property({ type: Node, tooltip: "格子父节点" })
    gridParent: Node | null = null;
    @property({ type: CCInteger, tooltip: "行数" })
    numRows: number = 9;
    @property({ type: CCInteger, tooltip: "列数" })
    numCols: number = 9;
    gridNodes: Node[][] = [];
    gridState: number[][] = [];
    catPos: { row: number, col: number } = { row: 4, col: 4 };
    obstacleCount: number = 20;
    onLoad() {
        CircleTheCat_GameManager.Instance = this;

        this.Init();

        this.createGridMap();
        this.initMapState();
        this.syncGridStateToView();
    }
    async Init() {
        CircleTheCat_GameStorage.initData();
        // CircleTheCat_GameData.InitData();


        CircleTheCat_GamePanel.Instance.ShowOn();
    }
    createGridMap() {
        this.gridParent.removeAllChildren();
        this.gridNodes = [];
        const cellW = 70;
        const cellH = 70;
        const startX = -(this.numCols - 1) * cellW / 2;
        const startY = (this.numRows - 1) * cellH / 2;

        for (let row = 0; row < this.numRows; row++) {
            this.gridNodes[row] = [];
            for (let col = 0; col < this.numCols; col++) {
                let gridNode = instantiate(this.gridPrefab);
                let offsetX = (row % 2) * (cellW / 2);
                let x = startX + col * cellW + offsetX;
                let y = startY - row * (cellH * 0.85);
                gridNode.setPosition(x, y);
                this.gridParent.addChild(gridNode);

                // let gridComp = gridNode.getComponent("CircleTheCat_Grid");
                let gridComp = gridNode.getComponent(CircleTheCat_Grid);
                if (gridComp && gridComp.init) {
                    gridComp.init(row, col, this);
                }
                this.gridNodes[row][col] = gridNode;
            }
        }
    }
    //    // 初始化地图状态
    initMapState() {
        // 0=空，1=障碍，2=猫
        this.gridState = [];
        for (let row = 0; row < this.numRows; row++) {
            this.gridState[row] = [];
            for (let col = 0; col < this.numCols; col++) {
                this.gridState[row][col] = 0;
            }
        }
        // 猫在中心
        this.catPos = { row: Math.floor(this.numRows / 2), col: Math.floor(this.numCols / 2) };
        // 清除所有猫
        for (let r = 0; r < this.numRows; r++) {
            for (let c = 0; c < this.numCols; c++) {
                if (this.gridState[r][c] === 2) this.gridState[r][c] = 0;
            }
        }
        this.gridState[this.catPos.row][this.catPos.col] = 2;
        // 随机放置障碍
        let placed = 0;
        while (placed < this.obstacleCount) {
            let r = Math.floor(Math.random() * this.numRows);
            let c = Math.floor(Math.random() * this.numCols);
            // 不在边缘，不在猫上，不重复
            if (
                (r === 0 || r === this.numRows - 1 || c === 0 || c === this.numCols - 1) ||
                (r === this.catPos.row && c === this.catPos.col) ||
                this.gridState[r][c] !== 0
            ) {
                continue;
            }
            this.gridState[r][c] = 1;
            placed++;
        }
    }
    //    // 同步状态到格子显示
    syncGridStateToView() {
        let catCount = 0;
        for (let row = 0; row < this.numRows; row++) {
            for (let col = 0; col < this.numCols; col++) {
                let node = this.gridNodes[row][col];
                // let comp = node.getComponent("CircleTheCat_Grid");
                let comp = node.getComponent(CircleTheCat_Grid);
                if (comp) {
                    if (this.gridState[row][col] === 1) {
                        comp.setBlocked();
                    } else {
                        comp.isBlocked = false;
                        comp.updateState && comp.updateState();
                    }
                    // 显示猫
                    if (this.gridState[row][col] === 2) {
                        comp.showCat && comp.showCat(true);
                        comp.切换猫动作();
                        catCount++;
                    } else {
                        comp.showCat && comp.showCat(false);
                    }
                }
            }
        }
        console.log('catCount', catCount, 'catPos', this.catPos);
    }
    //    // 格子点击回调
    onCellClicked(row: number, col: number) {
        if (this.gridState[row][col] !== 0) return;
        this.gridState[row][col] = 1;
        let gridNode = this.gridNodes[row][col];
        // let gridComp = gridNode.getComponent("CircleTheCat_Grid");
        let gridComp = gridNode.getComponent(CircleTheCat_Grid);
        if (gridComp && gridComp.setBlocked) {
            gridComp.setBlocked();
        }
        // 玩家操作后，猫移动
        this.moveCat();
    }
    //    // 猫移动逻辑
    moveCat() {
        let { row, col } = this.catPos;
        if (this.isEdge(row, col)) {
            this.onGameLose();
            return;
        }
        let path = this.findPathToEdge(row, col);
        if (path && path.length > 1) {
            let next = path[1];
            // 检查是否相邻
            let neighbors = this.getNeighbors(row, col);
            let isNeighbor = neighbors.some(n => n.row === next.row && n.col === next.col);
            if (!isNeighbor) {
                console.error('猫试图跳到不相邻格子！', row, col, '->', next.row, next.col, 'neighbors:', neighbors);
                this.onGameLose();
                return;
            }
            console.log('cat from', row, col, 'to', next.row, next.col, 'neighbors:', neighbors);
            // 清除所有猫
            for (let r = 0; r < this.numRows; r++) {
                for (let c = 0; c < this.numCols; c++) {
                    if (this.gridState[r][c] === 2) this.gridState[r][c] = 0;
                }
            }
            // 只允许猫走到空格
            if (this.gridState[next.row][next.col] === 0) {
                this.gridState[next.row][next.col] = 2;
                this.catPos = { row: next.row, col: next.col };
                if (this.isEdge(next.row, next.col)) {
                    this.syncGridStateToView();
                    this.onGameLose();
                    return;
                }
                this.syncGridStateToView();
            } else {
                // 理论上不会发生
                this.syncGridStateToView();
                this.onGameWin();
            }
        } else {
            this.syncGridStateToView();
            this.onGameWin();
        }
    }
    //    // 玩家胜利
    onGameWin() {
        // TODO: 你可以在这里实现胜利UI
        console.log("onGameWin");
        UI.Instance.CreatePanel_sub(`CircleTheCat_Prefab`, `UI/CircleTheCat_WinPanel`, CircleTheCat_WinPanel);
    }
    //    // 玩家失败
    onGameLose() {
        // TODO: 你可以在这里实现失败UI
        console.log("onGameLose");
        UI.Instance.CreatePanel_sub(`CircleTheCat_Prefab`, `UI/CircleTheCat_LosePanel`, CircleTheCat_LosePanel);
    }
    isEdge(row: number, col: number) {
        return row === 0 || row === this.numRows - 1 || col === 0 || col === this.numCols - 1;
    }
    //    // 用 Node 坐标判断是否相邻
    isAdjacent(row1: number, col1: number, row2: number, col2: number): boolean {
        // 获取两个格子的 Node
        let node1 = this.gridNodes[row1][col1];
        let node2 = this.gridNodes[row2][col2];

        if (!node1 || !node2) return false;

        // 获取世界坐标
        let pos1 = node1.getPosition();
        let pos2 = node2.getPosition();

        // 计算欧几里得距离
        // let distance = pos1.sub(pos2).mag();

        let distance = Vec3.distance(pos1, pos2);

        // 相邻的格子距离应该接近格子大小
        return distance <= 70; // 略大于格子大小，容错
    }
    //    // 用 Node 坐标找相邻格子
    getNeighbors(row: number, col: number) {
        let result = [];
        // console.log('getNeighbors for', row, col);

        // 遍历所有格子，用 Node 坐标判断相邻
        for (let r = 0; r < this.numRows; r++) {
            for (let c = 0; c < this.numCols; c++) {
                if (this.isAdjacent(row, col, r, c) && this.gridState[r][c] === 0) {
                    result.push({ row: r, col: c });
                    // console.log('  neighbor:', r, c);
                }
            }
        }
        // console.log('neighbors result:', result);
        return result;
    }
    //    // BFS找最短路径到边缘
    findPathToEdge(row: number, col: number) {
        let visited = Array.from({ length: this.numRows }, () => Array(this.numCols).fill(false));
        let queue = [];
        let prev = Array.from({ length: this.numRows }, () => Array(this.numCols).fill(null));
        queue.push({ row, col });
        visited[row][col] = true;
        while (queue.length > 0) {
            let curr = queue.shift();
            if (this.isEdge(curr.row, curr.col) && !(curr.row === row && curr.col === col)) {
                let path = [];
                let p = curr;
                while (p) {
                    path.unshift(p);
                    p = prev[p.row][p.col];
                }
                return path;
            }
            for (let n of this.getNeighbors(curr.row, curr.col)) {
                if (!visited[n.row][n.col]) {
                    visited[n.row][n.col] = true;
                    prev[n.row][n.col] = curr;
                    queue.push(n);
                }
            }
        }
        return null;
    }
    //    /** 重玩 */
    Replay() {
        this.initMapState();
        this.syncGridStateToView();

        let currentSceneName = director.getScene().name;
        director.loadScene(currentSceneName);
    }
}